<?php

/**
 * 
 *    建造者模式也称生成器模式，核心思想是将一个复杂对象的构造与它的表示分离，
 *    使同样的构建过程可以创建不同的表示，这样的设计模式被称为建造者模式。  
  *   例如：汽车，他的发动机引擎有好多品牌，轮胎也有各种材质，内饰更是千奇百怪；
 *   鸟，他的头、翅膀以及脚有各种颜色和形状，在创建这种复杂对象的时候，我们建议使用建造者模式。
 *
 * 
 *    建造者模式一般认为有四个角色：
  *    1.产品角色，产品角色定义自身的组成属性
  *    2.抽象建造者，抽象建造者定义了产品的创建过程以及如何返回一个产品
  *    3.具体建造者，具体建造者实现了抽象建造者创建产品过程的方法，给产品的具体属性进行赋值定义
  *    4.指挥者，指挥者负责与调用客户端交互，决定创建什么样的产品
 *
 * 使用场景： 1、需要生成的对象具有复杂的内部结构。 2、需要生成的对象内部属性本身相互依赖。
 * 
 * 意图：将一个复杂的构建与其表示相分离，使得同样的构建过程可以创建不同的表示。

    主要解决：主要解决在软件系统中，有时候面临着"一个复杂对象"的创建工作，其通常由各个部分的子对象用一定的算法构成；由于需求的变化，这个复杂对象的各个部分经常面临着剧烈的变化，但是将它们组合在一起的算法却相对稳定。
    
    何时使用：一些基本部件不会变，而其组合经常变化的时候。
    
    如何解决：将变与不变分离开。
    
    关键代码：建造者：创建和提供实例，导演：管理建造出来的实例的依赖关系。
    
    应用实例： 1、去肯德基，汉堡、可乐、薯条、炸鸡翅等是不变的，而其组合是经常变化的，生成出所谓的"套餐"。 2、JAVA 中的 StringBuilder。
    
    优点： 1、建造者独立，易扩展。 2、便于控制细节风险。
    
    缺点： 1、产品必须有共同点，范围有限制。 2、如内部变化复杂，会有很多的建造类。
    
    使用场景： 1、需要生成的对象具有复杂的内部结构。 2、需要生成的对象内部属性本身相互依赖。
    
    注意事项：与工厂模式的区别是：建造者模式更加关注与零件装配的顺序
 * 
 */

/**
 * 具体产品角色 鸟类
 * Class Bird
 */
class Bird
{

    public $_head;

    public $_wing;

    public $_foot;

    function show()
    {
        echo "头的颜色:{$this->_head}<br/>";
        echo "翅膀的颜色:{$this->_wing}<br/>";
        echo "脚的颜色:{$this->_foot}<br/>";
    }
}

/**
 * 抽象鸟的建造者(生成器)
 * Class BirdBuilder
 */
abstract class BirdBuilder
{

    protected $_bird;

    function __construct()
    {
        $this->_bird = new Bird();
    }

    abstract function BuildHead();

    abstract function BuildWing();

    abstract function BuildFoot();

    abstract function GetBird();
}

/**
 * 具体鸟的建造者(生成器) 蓝鸟
 * Class BlueBird
 */
class BlueBird extends BirdBuilder
{

    function BuildHead()
    {
        // TODO: Implement BuilderHead() method.
        $this->_bird->_head = "Blue";
    }

    function BuildWing()
    {
        // TODO: Implement BuilderWing() method.
        $this->_bird->_wing = "Blue";
    }

    function BuildFoot()
    {
        // TODO: Implement BuilderFoot() method.
        $this->_bird->_foot = "Blue";
    }

    function GetBird()
    {
        // TODO: Implement GetBird() method.
        return $this->_bird;
    }
}

/**
 * 玫瑰鸟
 * Class RoseBird
 */
class RoseBird extends BirdBuilder
{

    function BuildHead()
    {
        // TODO: Implement BuildHead() method.
        $this->_bird->_head = "Red";
    }

    function BuildWing()
    {
        // TODO: Implement BuildWing() method.
        $this->_bird->_wing = "Black";
    }

    function BuildFoot()
    {
        // TODO: Implement BuildFoot() method.
        $this->_bird->_foot = "Green";
    }

    function GetBird()
    {
        // TODO: Implement GetBird() method.
        return $this->_bird;
    }
}

/**
 * 指挥者
 * Class Director
 */
class Director
{

    /**
     *
     * @param $_builder 建造者            
     * @return mixed 产品类：鸟
     */
    function Construct(BirdBuilder $_builder)
    {
        $_builder->BuildHead();
        $_builder->BuildWing();
        $_builder->BuildFoot();
        return $_builder->GetBird();
    }
}

// ------------------------生成器模式测试代码------------------

$director = new Director();

echo "蓝鸟的组成：<hr/>";

$blue_bird = $director->Construct(new BlueBird());
$blue_bird->Show();

echo "<br/>Rose鸟的组成：<hr/>";

$rose_bird = $director->Construct(new RoseBird());
$rose_bird->Show();

// 汽车零件
abstract class Car
{

    public $part = [];

    function seTPart($key, $val)
    {
        $this->part[$key] = $val;
    }

    function show()
    {
        var_dump($this->part);
    }
}

// 建造者接口
interface CarBuilderInterface
{

    public function createCar();

    public function addWheel();

    public function addEngine();

    public function addDoors();

    public function getCar(): Car;
}

// 卡车
class TruckCar extends Car
{
}

// 卡车建造者
class TruckCarBuilder implements CarBuilderInterface
{

    private $truck;

    /**
     *
     * {@inheritdoc}
     *
     * @see CarBuilderInterface::createVehicle()
     */
    public function createCar()
    {
        // TODO Auto-generated method stub
        $this->truck = new TruckCar();
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see CarBuilderInterface::addWheel()
     */
    public function addWheel()
    {
        // TODO Auto-generated method stub
        $this->truck->setPart('rightDoor', "door");
        $this->truck->setPart('leftDoor', "door");
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see CarBuilderInterface::addEngine()
     */
    public function addEngine()
    {
        // TODO Auto-generated method stub
        $this->truck->setPart('truckEngine', "卡车的引擎");
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see CarBuilderInterface::addDoors()
     */
    public function addDoors()
    {
        // TODO Auto-generated method stub
        $this->truck->setPart('door1', "1");
        $this->truck->setPart('door2', "2");
        $this->truck->setPart('door3', "3");
        $this->truck->setPart('door4', "4");
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see CarBuilderInterface::getCar()
     */
    public function getCar(): Car
    {
        // TODO Auto-generated method stub
        return $this->truck;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see CarBuilderInterface::getProduct()
     */
    public function getProduct(): Car
    {
        // TODO Auto-generated method stub
    }
}

class BussCar extends Car
{
}

// 小汽车建造者
class BussCarBuilder implements CarBuilderInterface
{

    private $buss;

    /**
     *
     * {@inheritdoc}
     *
     * @see CarBuilderInterface::createVehicle()
     */
    public function createCar()
    {
        // TODO Auto-generated method stub
        $this->buss = new TruckCar();
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see CarBuilderInterface::addWheel()
     */
    public function addWheel()
    {
        // TODO Auto-generated method stub
        $this->buss->setPart('rightDoor', "door1");
        $this->buss->setPart('leftDoor', "door1");
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see CarBuilderInterface::addEngine()
     */
    public function addEngine()
    {
        // TODO Auto-generated method stub
        $this->buss->setPart('truckEngine', "小汽车的引擎");
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see CarBuilderInterface::addDoors()
     */
    public function addDoors()
    {
        // TODO Auto-generated method stub
        $this->buss->setPart('door1', "1");
        $this->buss->setPart('door2', "2");
        $this->buss->setPart('door3', "3");
        $this->buss->setPart('door4', "4");
        $this->buss->setPart('door5', "5");
        $this->buss->setPart('door6', "6");
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see CarBuilderInterface::getCar()
     */
    public function getCar(): Car
    {
        // TODO Auto-generated method stub
        return $this->buss;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see CarBuilderInterface::getProduct()
     */
    public function getProduct(): Car
    {
        // TODO Auto-generated method stub
    }
}

/**
 * Director 类是建造者模式的一部分。 它可以实现建造者模式的接口
 * 并在构建器的帮助下构建一个复杂的对象
 *
 * 您也可以注入许多构建器而不是构建更复杂的对象
 */
class CarDirector
{

    static public function build(CarBuilderInterface $builder): Car
    {
        $builder->createCar();
        $builder->addDoors();
        $builder->addEngine();
        $builder->addWheel();
        
        return $builder->getCar();
    }
}

CarDirector::build(new TruckCarBuilder())->show();
CarDirector::build(new BussCarBuilder())->show();

/*
 * 商业案例 作业
 *  我们假设一个快餐店的商业案例，其中，一个典型的套餐可以是一个汉堡（Burger）和一杯冷饮（Cold drink）。
* 汉堡（Burger）可以是素食汉堡（Veg Burger）或鸡肉汉堡（Chicken Burger），它们是包在纸盒中。
* 冷饮（Cold drink）可以是可口可乐（coke）或百事可乐（pepsi），它们是装在瓶子中。
* */
